---
title: 'Using the @defer and @stream directives in Apollo Kotlin'
description: 'Fetch slower schema fields asynchronously'
---

<Note>

The incremental delivery format used by `@defer`/`@stream` [isn't yet standardized](https://github.com/graphql/defer-stream-wg). Apollo Kotlin supports [the format implemented by Apollo Router](https://www.apollographql.com/docs/graphos/routing/operations/defer#specification-status), which is described in this [specification](https://specs.apollo.dev/incremental/v0.1/), and the more recent format described in this [specification](https://specs.apollo.dev/incremental/v0.2/)

</Note>

The [`@defer` directive](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md) enables your queries to receive data for specific fields incrementally, instead of receiving all field data at the same time. This is helpful when some fields in a query take much longer to resolve than others.

For example, let's say we're building a social media application that can quickly fetch a user's basic profile information, but retrieving that user's friends takes longer. If we include _all_ of those fields in a single query, we want to be able to display the profile information as soon as it's available, instead of waiting for the friend fields to resolve.

To achieve this, we can apply the `@defer` directive to an inline fragment that contains all slow-resolving fields related to friend data:

```graphql
query PersonQuery($personId: ID!) {
  person(id: $personId) {
    # Basic fields (fast)
    id
    firstName
    lastName

    # highlight-start
    # Friend fields (slower)
    ... on User @defer {
      friends {
        id
      }
    }
    # highlight-end
  }
}
```

In the generated code for this query, the `onUser` field for the fragment will be nullable. That is because when the initial payload is received from the server, the fields of the fragment are not yet present. A `Person` will be emitted with only the basic fields filled in.

When the fields of the fragment are available, a new `Person` will be emitted, this time with the `onUser` field present and filled with the fields of the fragment.

```kotlin
apolloClient.query(PersonQuery(personId)).toFlow().collect {
  println("Received: $it")
  if (it.dataOrThrow().person.onUser == null) {
    // Initial payload: basic info only
    // ...
  } else {
    // Subsequent payload: with friends
    // ...
  }
}
```

Will print something like this:

```
Received: Person(id=1, firstName=John, lastName=Doe, onUser=null))
Received: Person(id=1, firstName=John, lastName=Doe, onUser=OnUser(friends=[Friend(id=2), Friend(id=3)]))
```

### `@stream` directive support
Similarly to `@defer`, the `@stream` directive can be used to receive the first few items of **lists** in the initial response, while the remaining items arrive later.

Note: this directive is only supported when using the [v0.2](https://www.apollographql.com/docs/kotlin/kdoc/apollo-runtime/com.apollographql.apollo.network/-incremental-delivery-protocol/-v0_2/index.html) protocol:

```kotlin
apolloClient = ApolloClient.Builder()
  .networkTransport(
    HttpNetworkTransport.Builder()
      .serverUrl("https://...")
      // Configure the incremental v0.2 protocol // highlight-line
      .incrementalDeliveryProtocol(IncrementalDeliveryProtocol.V0_2) // highlight-line
      .build()
  )
  .build()
```

For example this query:
```graphql
query FriendsQuery {
  friends @stream(initialCount: 2) {
    firstName
  }
}
```

Will print something like this:

```
Received: friends=[Person(firstName=John), Person(firstName=Jane)]
Received: friends=[Person(firstName=John), Person(firstName=Jane), Person(firstName=Michael), Person(firstName=Patricia), Person(firstName=James)]
```

### Error handling
When using `@defer`, the incremental payloads received from the server may each contain GraphQL errors related to the fields being returned.
These errors are accumulated and exposed in the [`ApolloResponse.errors`](https://apollographql.github.io/apollo-kotlin/kdoc/apollo-api/com.apollographql.apollo.api/-apollo-response/errors.html) field.

Fetch errors like network failures can also happen during collection of the flow, and will be exposed in [`ApolloResponse.exception`](https://apollographql.github.io/apollo-kotlin/kdoc/apollo-api/com.apollographql.apollo.api/-apollo-response/exception.html)

See also the [error handling section](../essentials/errors).

### Support matrix

| Protocol | Compatible servers           | Supported directives |
|----------|------------------------------|----------------------|
| v0.1     | Apollo Router, Apollo Server | `@defer`             |
| v0.2     | Apollo Server                | `@defer`, `@stream`  |



### Limitations/known issues
* `@defer` cannot be used with `responseBased` codegen.
* Some servers might send an empty payload to signal the end of the stream. In such a case you will receive an extra terminal emission. You can filter it out by using `distinctUntilChangedBy()`:

```kotlin
apolloClient.query(MyQuery()).toFlow()
    .distinctUntilChangedBy { it.data }  // filter out duplicates
    .collect { /* ... */ }
```
